﻿
#pragma once

#include <vector>
#include <array>
#include <string>

enum FlipFlag {
    NoFlip = 0x0000,
    Horizontal = 0x0001,
    Vertical = 0x0002,
    HorVer = Horizontal | Vertical
};

namespace Coordinate {
struct SCoordinate {
    std::array<int, 4> coordinate;//x1,y1,x2,y2

    SCoordinate()
    {
        for (int i = 0; i < 4; i++) {
            coordinate[i] = 0;
        }
    }

    SCoordinate(int x1, int y1, int x2, int y2)
    {

        coordinate[0] = x1;
        coordinate[1] = y1;
        coordinate[2] = x2;
        coordinate[3] = y2;

        diagonalchange(coordinate);
    }

    template<class Arr>
    SCoordinate(Arr argarr)
    {
        for (int i = 0; i < 4; i++) {
            coordinate[i] = argarr[i];
        }
        diagonalchange(coordinate);
    }
    SCoordinate operator*(double arg_enlarge_rate)
    {
        SCoordinate tmp;
        for (int i = 0; i < 4; i++) {
            tmp.coordinate[i] = coordinate[i] * arg_enlarge_rate;
        }
        return tmp;
    }
    SCoordinate operator*(std::pair<double, double> arg_enlarged_rate)
    {
        SCoordinate tmp;
        tmp.coordinate[0] = coordinate[0] * arg_enlarged_rate.first;
        tmp.coordinate[1] = coordinate[1] * arg_enlarged_rate.second;
        tmp.coordinate[2] = coordinate[2] * arg_enlarged_rate.first;
        tmp.coordinate[3] = coordinate[3] * arg_enlarged_rate.second;
        return tmp;
    }
    static int diagonalchange(int temp[4])
    {

        int vector[2] = { temp[2] - temp[0], temp[3] - temp[1] };

        if (vector[0] < 0) {
            temp[0] += vector[0];
            temp[2] -= vector[0];
        }
        if (vector[1] < 0) {
            temp[1] += vector[1];
            temp[3] -= vector[1];
        }

        return 0;
    }
    static int diagonalchange(std::array<int, 4> &temp)
    {

        int vector[2] = { temp[2] - temp[0], temp[3] - temp[1] };

        if (vector[0] < 0) {
            temp[0] += vector[0];
            temp[2] -= vector[0];
        }
        if (vector[1] < 0) {
            temp[1] += vector[1];
            temp[3] -= vector[1];
        }

        return 0;
    }
    static SCoordinate reverseX(const SCoordinate &a_)
    {
        SCoordinate ret;
        ret.coordinate = a_.coordinate;
        ret.coordinate[0] *= -1;
        ret.coordinate[2] *= -1;
        diagonalchange(ret.coordinate);
        return ret;
    }
};

struct SClsn {
private:
    std::vector<SCoordinate> Clsn;
public:
    SClsn operator*(double arg_enlarge_rate)
    {
        if (arg_enlarge_rate == 1)
            return *this;

        SClsn tmp;
        for (auto it = Clsn.begin(); it != Clsn.end(); it++) {
            tmp.push_back((*it)*arg_enlarge_rate);
        }
        return tmp;
    }
    SClsn operator*(std::pair<double, double> arg_enlarged_rate)
    {
        SClsn tmp_clsn;
        for (auto it = Clsn.begin(); it != Clsn.end(); it++) {
            tmp_clsn.push_back((*it)*arg_enlarged_rate);
        }
        return tmp_clsn;
    }
    SCoordinate operator[](unsigned int arg_index)
    {
        if (arg_index > Clsn.size() - 1)
            return SCoordinate();
        return Clsn[arg_index];
    }
    SClsn operator+(std::pair<int, int> add)
    {
        SClsn output;
        for (auto it = Clsn.cbegin(); it != Clsn.cend(); it++) {
            auto &elem = it->coordinate;
            output.push_back(SCoordinate{ elem[0] + add.first, elem[1] + add.second, elem[2] + add.first, elem[3] + add.second });
        }
        return output;
    }
    SClsn &operator=(std::vector<SCoordinate> arg)
    {
        Clsn = arg;
        return *this;
    }
    void push_back(SCoordinate arg)
    {
        Clsn.push_back(arg);
        return;
    }

    unsigned int size()
    {
        return Clsn.size();
    }

    const std::vector<SCoordinate> &GetClsn()const
    {
        return Clsn;
    }
};
}

struct SFrame {
    Coordinate::SClsn Clsn1;
    Coordinate::SClsn Clsn2;

    int Image;
    int Group;
    int Delay;

    FlipFlag FlipF;
    int layer;//0�Œʏ�A�P�œ��߁A2�Ō��Z
    int AS;
    int D;
    SFrame()
    {
        Image = -1;
        Group = -1;
        Delay = 1;
        FlipF = FlipFlag::NoFlip;
        layer = 0;
        AS = 255;
        D = 255;
    }
};

struct SAnim {
private:
    std::vector<SFrame> m_frameVector;//�f�[�^�̍Ō�̖ڈ�ɁASframe�̃R���X�g���N�^���������̃f�[�^�������Ă܂�
public:
    int loop = -1;//0���琔����loop�Ԗڂ̉摜���烋�[�v������B    -1�Ȃ烋�[�v���Ȃ�
    int Dec(FILE *&fp);
    SAnim()
    {
    }

    SFrame &operator[](unsigned int argindex)
    {
        if (argindex >= m_frameVector.size()) {
            if (m_frameVector.size() == 0) {
                SFrame tmp{};
                m_frameVector.push_back(tmp);
            }
            return m_frameVector[0];
        } else
            return m_frameVector[argindex];
    }
    const SFrame &operator[](unsigned int argindex) const
    {
        return m_frameVector[argindex];
    }

    unsigned int Size() const { return m_frameVector.size(); }

    int GetMaxAirFrame()
    {
        int ret = 0;
        for (int i = 0, e = m_frameVector.size(); i < e; i++) {
            ret += m_frameVector[i].Delay;
        }
        return ret;
    }

    int GetAirFrameIndexByMotionTime(int motiontime_)
    {
        int frame = 1;
        int airinddexOfTheFrame = 0;
        for (int e = m_frameVector.size(); airinddexOfTheFrame < e; airinddexOfTheFrame++) {
            frame += m_frameVector[airinddexOfTheFrame].Delay;
            if (motiontime_ <= frame) {
                break;
            }
        }

        return airinddexOfTheFrame;
    }

    SFrame &GetAirFrameByMotionTime(int motiontime_)
    {
        int frame = 1;
        int airinddexOfTheFrame = 0;
        for (int e = m_frameVector.size(); airinddexOfTheFrame < e; airinddexOfTheFrame++) {
            frame += m_frameVector[airinddexOfTheFrame].Delay;
            if (motiontime_ <= frame) {
                break;
            }
        }

        return m_frameVector[airinddexOfTheFrame];
    }
};

struct Action {
    std::string Name;
    int Id;
    SAnim Ani;
};

class AirManager
{
public:
    int DecAir(const char *filename);
    const std::vector<Action> &GetActionVector()
    {
        return m_actionVector;
    }

private:
    std::vector<Action> m_actionVector;
};
